//
//  shhTunnel.m
//  Genesis
//
//  Created by Kristoffer Andersen on 31/12/08.
//  Copyright 2008 Kristoffer Andersen. All rights reserved.
//
//  This file is part of Genesis.
//  
//  Genesis is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//  
//  Genesis is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//  
//  You should have received a copy of the GNU General Public License
//  along with Genesis.  If not, see <http://www.gnu.org/licenses/>.


#import "shhTunnel.h"


@implementation shhTunnel

-(void)initSSHTunnel:(NSString *)aUsername host:(NSString *)remoteHost portLocalForward:(int)localPort portRemoteForward:(int)remotePort forwardHost:(NSString *)hostToForward forwardDest:(NSString*)destToForward
{
	//Setup ssh args
	username = aUsername;
	sshHost = remoteHost;
	forwardHost = hostToForward;
	forwardDest = destToForward;
	fLocalPort = localPort;
	fRemotePort = remotePort;	
}

-(void)connectSSH
{
	//Create the task and its pipes and handles
	ssh = [[NSTask alloc] init];
	outputPipe = [NSPipe pipe];
	inputPipe = [NSPipe pipe];
	outputHandle = [outputPipe fileHandleForReading];
	inputHandle = [inputPipe fileHandleForWriting];
	
	//Create environment
	NSMutableDictionary *env = [[NSMutableDictionary alloc] init];
	[env setObject:@"path" forKey:@"SSH_ASKPASS"];
	
	//Setup task
	[ssh setStandardError:outputPipe];
	[ssh setStandardOutput:outputPipe];
	[ssh setStandardInput:inputPipe];
	[ssh setLaunchPath:@"/usr/bin/ssh"];
	
	
	
	//Setup handle noticications
	[outputHandle readInBackgroundAndNotify];
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(outputNotification:) name:NSFileHandleReadCompletionNotification object:outputHandle];
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskDidEndNotification:) name:NSTaskDidTerminateNotification object:nil];
	
	//Args for ssh
	NSString *forward = [[NSMutableString alloc] initWithFormat:@"LocalForward %@:%i %@:%i",forwardDest,fLocalPort,forwardHost,fRemotePort];
	NSLog(forward);
	NSArray *args = [[NSArray alloc] initWithObjects:@"-C",@"-T",@"-v",@"-o",forward,@"-l",username,sshHost,nil];
	//-o "LocalForward localhost:5480 localhost:548" 
	//Execute
	willTerminate = NO;
	[ssh setArguments:args];
	[ssh launch];
}

-(void)terminateSSH
{
	if (ssh) {
		if ([ssh isRunning]) {
			willTerminate = YES;
			[ssh terminate];
		} else {
			[ssh release];
		}
	}
	/*[outputHandle release];
	[outputPipe release];*/
}

-(void)outputNotification:(NSNotification *)aNotification
{
	
	NSString *output = [[NSString alloc] initWithData:[[aNotification userInfo] objectForKey: NSFileHandleNotificationDataItem] encoding:NSUTF8StringEncoding];
	//printf([output cStringUsingEncoding:NSUTF8StringEncoding]);

	[[NSNotificationCenter defaultCenter]
	 postNotificationName:@"ConnectionDidPostText" object:output];
	
	if ([output rangeOfString:@"Entering interactive session."].location != NSNotFound) {
		//Tunnel done, post notits
		[[NSNotificationCenter defaultCenter]
		 postNotificationName:@"ConnectionSucces" object:output];
	}
	
	if (![ssh isRunning] && willTerminate == NO) {
		
		[[NSNotificationCenter defaultCenter] postNotificationName:@"ConnectionDidPostText" object:@"SSH ended unexpectedly!\n"];
		[[NSNotificationCenter defaultCenter]
		 postNotificationName:@"ConnectionInterupted" object:output];
	}
	else { //Only maintain notifications if ssh is running
		[outputHandle readInBackgroundAndNotify];
	}
	
}

-(void)taskDidEndNotification:(NSNotification *)aNotification
{
	if (willTerminate) {
		//Fjern observer hvis lukning planlagt
		[[NSNotificationCenter defaultCenter] postNotificationName:@"ConnectionDidPostText" object:@"SSH ended!\n"];
		//[[NSNotificationCenter defaultCenter] postNotificationName:@"ConnectionDidEndNotification" object:nil];
		[[NSNotificationCenter defaultCenter] removeObserver:self];
	}
	[ssh release];
	ssh = nil;
}

@end
